#ifndef XYGRID_H
#define XYGRID_H

/**
 * \file XYGrid.h
 * \brief Fichier contenant la déclaration de la classe XYGrid
 */

#include "GridFrame.h"

class XYGrid
{
	/* \class XYGrid
	 * \brief Cette classe représente une grille régulière selon xOy qui va découper le nuage de point initial en plusieurs sous-nuages. Un sous-nuage équivaut à une case de cette grille.
	 */
	private :
	
	Point bot;							/*!<Point le blus en bas à gauche de la grille.*/
	Point top;							/*!<Point le blus en haut à droite de la grille.*/
	int nbFrameX;						/*!<Nombre de cases selon Ox de la grille.*/
	int nbFrameY;						/*!<Nombre de cases selon Oy de la grille.*/
	float frameWidth;					/*!<Taille des cases de la grille selon Ox.*/
	float frameHeight;					/*!<Taille des cases de la grille selon Ox.*/
	vector< vector<GridFrame> > data;	/*!<Tableau à deux dimension de cases ( GridFrame ) contenant les données.*/

	public :
	
	/*!
     *  \brief Constructeur de la classe XYGrid
     *
     *  Constructeur de la classe XYGrid
     */
	XYGrid();
	
	/*!
     *  \brief Constructeur de la classe XYGrid
     *
     *  Constructeur de la classe XYGrid
	 *
	 * \param _p : Nuage de point sur lequel on applique la grille.
     * \param _xMin : Abscisse minimale du nuage de point _p.
	 * \param _yMin : Ordonnée minimale du nuage de point _p.
	 * \param _xMax : Abscisse maximale du nuage de point _p.
	 * \param _yMax : Ordonnée maximale du nuage de point _p.
	 * \param _resX : Resolution de la grille selon l'axe Ox (Nombre de case sur cet axe).
	 * \param _resY : Resolution de la grille selon l'axe Oy (Nombre de case sur cet axe).
	 */
	XYGrid( PointCloud _p, float _xMin, float _yMin, float _xMax, float _yMax, int _resX, int _resY );
	
	/*!
     *  \brief Méthode qui crée une grille régulière à partir d'un nuage de point déjà existant.
     *
     * Méthode qui crée une grille régulière à partir d'un nuage de point déjà existant.
	 *
	 * \param _p : Nuage de point sur lequel on applique la grille.
     * \param _xMin : Abscisse minimale du nuage de point _p.
	 * \param _yMin : Ordonnée minimale du nuage de point _p.
	 * \param _xMax : Abscisse maximale du nuage de point _p.
	 * \param _yMax : Ordonnée maximale du nuage de point _p.
	 * \param _resX : Resolution de la grille selon l'axe Ox (Nombre de case sur cet axe).
	 * \param _resY : Resolution de la grille selon l'axe Oy (Nombre de case sur cet axe).
	 * \return : void
	 */
	void getGridFromCloud( PointCloud _p, float _xMin, float _yMin, float _xMax, float _yMax, int _resX, int _resY );
	
	/*!
     *  \brief Accesseur de la classe XYGrid
     *
     *  Accesseur de la classe XYGrid : donne la réslution de la grille selon Ox.
	 *
	 * \return : Renvoie la valeur de l'attribut nbFrameX de l'objet.
	 */
	int getNbFrameX ();
	
	/*!
     *  \brief Accesseur de la classe XYGrid
     *
     *  Accesseur de la classe XYGrid : donne la réslution de la grille selon Oy.
	 *
	 * \return : Renvoie la valeur de l'attribut nbFrameY de l'objet.
	 */
	int getNbFrameY ();

	/*!
     *  \brief Accesseur de la classe XYGrid
     *
     *  Accesseur de la classe XYGrid : donne la taille des cases de la grille selon Ox.
	 *
	 * \return : Renvoie la valeur de l'attribut frameWidth de l'objet.
	 */
	float getFrameWidth ();

	/*!
     *  \brief Accesseur de la classe XYGrid
     *
     *  Accesseur de la classe XYGrid : donne la taille des cases de la grille selon Oy.
	 *
	 * \return : Renvoie la valeur de l'attribut frameHeight de l'objet.
	 */
	float getFrameHeight ();
	
	/*!
     *  \brief Accesseur de la classe XYGrid : donne la taille du nuage de points de la case (_i, _j).x
     *
     *  Accesseur de la classe XYGrid : donne la taille du nuage de points de la case (_i, _j).
	 *
	 * \return : Renvoie la taille du nuage de points de la case (_i, _j).
	 */
	int getSizeOfFrameCloud ( int _i, int _j );
			
	/*!
     *  \brief Modificateur de la classe XYGrid
     *
     *  Modificateur de la classe XYGrid
	 *
	 * \param _nbFrame : _nbFrame sera affecté à l'attribut nbFrameX de l'objet.
	 * \return : void
	 */
	void setNbFrameX ( int _nbFrame );
	
	/*!
     *  \brief Modificateur de la classe XYGrid
     *
     *  Modificateur de la classe XYGrid
	 *
	 * \param _nbFrame : _nbFrame sera affecté à l'attribut nbFrameY de l'objet.
	 * \return : void
	 */
	void setNbFrameY ( int _nbFrame );
	
	/*!
     *  \brief Affiche la grille.
     *
     *  Affiche la grille.
	 *
	 * \return : void
	 */
	void displayGrid ();
	
	/*!
     *  \brief Affiche la grille à une hauteur donnée.
     *
     *  Affiche la grille à la hauteur _z.
	 *
	 *  \param _z : hauteur à laquelle on souhaite afficher la grille.
	 *
	 * \return : void
	 */
	void displayGrid( float _z );
	
	/*!
     *  \brief Affiche le nuage de point de la case _i, _j de la grille.
     *
     *  Affiche le nuage de point de la case _i, _j de la grille.
	 *  \param _i : Indice selon Ox de la case de la grille que l'on veut visualiser.
	 *  \param _j : Indice selon Oy de la case de la grille que l'on veut visualiser.
	 *
	 * \return : void
	 */
	void displayIJCloud ( int _i, int _j );
	
	/*!
     *  \brief Affiche le nuage de point de la case _i, _j de la grille et la case de la grille en opaque à la hauteur _z.
     *
     *  Affiche le nuage de point de la case _i, _j de la grille et la case de la grille en opaque à la hauteur _z
	 *  \param _i : Indice selon Ox de la case de la grille que l'on veut visualiser.
	 *  \param _j : Indice selon Oy de la case de la grille que l'on veut visualiser.
	 *  \param _z : Hauteur ou l'on dessine la case de facon opaque.
	 *
	 * \return : void
	 */
	void displayIJCloud ( int _i, int _j, float _z );
	
	/*!
     *  \brief Affiche le nuage de point de la case _i, _j de la grille.
     *
     *  Affiche le nuage de point de la case _i, _j de la grille.
	 *  \param _i : Indice selon Ox de la case de la grille que l'on veut visualiser.
	 *  \param _j : Indice selon Oy de la case de la grille que l'on veut visualiser.
	 *  \param _z : Hauteur ou l'on dessine la case de facon opaque.
	 *  \param _r : Canal rouge de la couleur a afficher.
	 *  \param _g : Canal vert de la couleur a afficher.
	 *  \param _b : Canal bleu de la couleur a afficher.
	 *
	 * \return : void
	 */
	void displayIJCloud ( int _i, int _j, float _z, float _r, float _g, float _b );
	
	/*!
     *  \brief Seuille le nuage de points d'une case de la grille selon la hauteur. Méthode essentiellement utilisée lors des tests.
	 *
     *  Seuille le nuage de points d'une case de la grille selon la hauteur. Méthode essentiellement utilisée lors des tests.
	 *
	 *  \param _i : indice de la case à seuiller le long de l'axe Ox.
	 *  \param _j : indice de la case à seuiller le long de l'axe Oy.
	 *  \param _zMin : seuil bas de hauteur.
	 *  \param _zMax : seuil haut de hauteur.
	 *
	 *  \return : void
     */
	void keepPointsBetween(int _i, int _j, float _zMin, float _zMax);
	
	/*!
     *  \brief Accede au point inferieur gauche d'une case de la grille.
	 *
     *  Accede au point inferieur gauche d'une case de la grille.
	 *
	 *  \param _i : indice de la case à acceder selon Ox.
	 *  \param _j : indice de la case à acceder selon Oy.
	 *
	 *  \return : Renvoie le point inferieur gauche de la case (_i, _j).
     */
	Point getFrameBotPoint ( int _i, int _j );
	
	/*!
     *  \brief Accede au point superieur droit d'une case de la grille.
	 *
     *  Accede au point superieur droit d'une case de la grille.
	 *
	 *  \param _i : indice de la case à acceder selon Ox.
	 *  \param _j : indice de la case à acceder selon Oy.
	 *
	 *  \return : Renvoie le point superieur droit de la case (_i, _j).
     */
	Point getFrameTopPoint ( int _i, int _j );
	
	/*!
     *  \brief Récupère l'ensemble des cercles à partir du nuage de points de la case (i,j).
	 *
     *  Remplit le tableau de cercles à partir des triplets de points trouvés dans le nuage de points de la case de coordonnées (i,j).
	 *
	 *  \param _tabCircles : vector de cercles à remplir.
	 *  \param _i : coordonnée i de la case conteant le nuage.
	 *  \param _j : coordonnée j de la case conteant le nuage.
	 *
	 *  \return : void
     */
	void getFrameCircles(vector <Circle> & _tabCircles, int _i, int _j);

	/*!
     *  \brief Récupère l'ensemble des cercles à partir du nuage de points de la case (i,j).
	 *
     *  Remplit directement l'espace de Hough à partir des triplets de points trouvés dans le nuage de points de la case de coordonnées (i,j).
	 *
	 *  \param _hs : Espace de Hough à remplir.
	 *  \param _rMax : Rayon max des cercles à chercher.
	 *  \param _i : coordonnée i de la case conteant le nuage.
	 *  \param _j : coordonnée j de la case conteant le nuage.
	 *
	 *  \return : void
     */
	void getFrameCircles(HoughSpace & _hs, float _rMax, int _i, int _j);

	/*!
	 *  \brief Récupère l'ensemble des cercles à partir du nuage de points de la case (i,j).
	 *
     *  Remplit directement l'espace de Hough à partir des triplets de points trouvés dans le nuage de points de la case de coordonnées (i,j) en appliquant un certain coefficient.
	 *
	 *  \param _hs : Espace de Hough à remplir.
	 *  \param _rMax : Rayon max des cercles à chercher.
	 *  \param _i : coordonnée i de la case conteant le nuage.
	 *  \param _j : coordonnée j de la case conteant le nuage.
	 *  \param _coef : Coefficiant permettant de donner plus ou moins de poid aux cercles trouvés.
	 *
	 *  \return : void
     */
	void getFrameCircles(HoughSpace & _hs, float _rMax, int _i, int _j, int _coef);
	
	/*!
     *  \brief Récupère l'ensemble des cercles à partir du nuage de points de toutes les cases de la grille.
	 *
     *  Remplit le tableau de cercles à partir des triplets de points trouvés dans le nuage de points de toutes les cases de la grille.
	 *
	 *  \param _tabCircles : vector de cercles à remplir.
	 *
	 *  \return : void
     */
	void getAllCircles( vector <Circle> &_tabCircles );

	/*!
     *  \brief Récupère l'ensemble des cercles à partir du nuage de points de toutes les cases de la grille.
	 *
     *  Remplit directement l'espace de Hough à partir des triplets de points trouvés dans le nuage de points de toutes les cases de la grille.
	 *
	 *  \param _hs : Espace de Hough à remplir.
	 *  \param _rMax : Rayon max des cercles à chercher.
	 *
	 *  \return : void
     */
	void getAllCircles(HoughSpace & _hs, float _rMax);
	
	/*!
     *  \brief Fait une coupe du nuage de points.
	 *
     *  Coupe le nuage de points de la case à partir de deux seuils (min_case_courante+_bas et min_case_courante+_haut).
	 *
	 *  \param _bas : Seuil bas.
	 *  \param _haut : Seuil haut.
	 *
	 *  \return : void
     */
	void keepSlice ( float _bas, float _haut );
	
	/*!
     *  \brief Fait une coupe du nuage de points.
	 *
     *  Coupe le nuage de points en récupérant un certain nombre de points à partir d'un seuil.
	 *
	 *  \param _bas : Seuil bas.
	 *  \param _nbPoints : Nombre de points à récupérer au dessus de l'altitude seuil.
	 *
	 *  \return : void
     */
	void keepSlice ( float _bas, int _nbPoints );
	
	/*!
     *  \brief Fait une coupe du nuage de points.
	 *
     *  Coupe le nuage de points en récupérant un certain nombre de points compris entre une hauteur minimale et maximale.
	 *
	 *  \param _bas : Seuil bas.
	 *  \param _haut : Seuil haut.
	 *  \param _nbPoints : Nombre de points à récupérer au dessus de l'altitude seuil.
	 *
	 *  \return : void
     */
	void keepSlice(float _bas, float _haut, int _nbPoints );
	
	/*!
     *  \brief Crée une coupe du nuage de points.
	 *
     *  Crée une nouvelle grille contenant une coupe du nuage de points à partir de deux seuils (min_case_courante+_bas et min_case_courante+_haut).
	 *
	 *  \param _bas : Seuil bas.
	 *  \param _haut : Seuil haut.
	 *
	 *  \return : Nouvelle XYGrid contenant la coupe.
     */
	XYGrid getSlice ( float _bas, float _haut );
	
	/*!
     *  \brief Crée une coupe du nuage de points.
	 *
     *  Crée une nouvelle grille contenant une coupe du nuage de points en récupérant un certain nombre de points à partir d'un seuil.
	 *
	 *  \param _bas : Seuil bas.
	 *  \param _nbPoints : Nombre de points à récupérer au dessus de l'altitude seuil.
	 *
	 *  \return : Nouvelle XYGrid contenant la coupe. 
     */
	XYGrid getSlice ( float _bas, int _nbPoints );
	
	/*!
     *  \brief Crée une coupe du nuage de points.
	 *
     *  Crée une nouvelle grille contenant une coupe du nuage de points en récupérant un certain nombre de points à partir d'un seuil.
	 *
	 *  \param _bas : Seuil bas.
	 *  \param _haut : Seuil haut.
	 *  \param _nbPoints : Nombre de points à récupérer au dessus de l'altitude seuil.
	 *
	 *  \return : Nouvelle XYGrid contenant la coupe. 
     */
	XYGrid getSlice ( float _bas, float _haut, int _nbPoints );
	
	/*!
     *  \brief Affiche les coordonnées extremes d'une case.
	 *
     *  Affiche les coordonnées extremes de la case de coordonnées (i,j).
	 *
	 *  \param _i : coordonnée i de la case.
	 *  \param _j : coordonnée j de la case.
	 *
	 *  \return : void
     */
	void printFrameBoundingSquare (int _i, int _j);
	
	/*!
     *  \brief Affiche les coordonnées extremes de la grille.
	 *
     *  Affiche les coordonnées extremes de la grille
	 *
	 *  \return : void
     */
	void printBoundingBox ();

	/*!
	*  \brief Trie les points du nuage de la case selon leur altitude.
	*
	* \return : void
	*/
	void Sort();
	
	/*!
     *  \brief Donne la hauteur du point le plus bas dans une case.
	 *
     *  Donne la hauteur du point le plus bas de la case (i,j) de la grille.
	 *
	 *  \param _i : coordonnée i de la case.
	 *  \param _j : coordonnée j de la case.
	 *
	 *  \return : Renvoie la hauteur du point minimum.
     */
	float getFrameZMin (int _i, int _j );
};

#endif
